$import( "SmitearWebGL.Objects.Mesh" );
$import( "SmitearWebGL.Core.Geometry.InputDataSet" );
$import( "SmitearWebGL.Core.Geometry.VertexDataSet" );

SmitearWebGL.Objects.Primitive.Sphere = SmitearWebGL.Objects.Mesh.extend(
{
	/* * * * * * * * constructor * * * * * * * */
	
	init : function()
	{
		this._super();
		this._registClass( "SmitearWebGL.Objects.Primitive.Sphere" );
	}
	,
	_build : function( radius, segmentsW, segmentsH )
	{
		var vertices = [];
		var uvs = [];
		var vIndices = [];
		var tIndices = [];
		var i, j, k = 0;
		var iHor = Math.max( 3, segmentsW );
		var iVer = Math.max( 2, segmentsH );
		var aVtc = new Array( iVer + 1 );
		for ( j = 0; j < ( iVer + 1 ); j ++ )
		{
			var fRad1 = j / iVer;
			var fZ = - radius * Math.cos( fRad1 * Math.PI );
			var fRds = radius * Math.sin( fRad1 * Math.PI );
			var aRow = new Array( iHor );
			var oVtx;
			for ( i = 0; i < iHor; i ++ )
			{
				var fRad2 = Number( 2 * i / iHor );
				var fX = fRds * Math.sin( fRad2 * Math.PI );
				var fY = fRds * Math.cos( fRad2 * Math.PI );
				if ( ! ( ( j == 0 || j == iVer ) && i > 0 ) )
				{
					vertices.push( fY, fZ, fX );
					oVtx = k;
					++ k;
				}
				aRow[i] = oVtx;
			}
			aVtc[j] = aRow;
		}
		k = 0;
		var iVerNum = aVtc.length;
		for ( j = 0; j < iVerNum; j ++ )
		{
			var iHorNum = aVtc[j].length;
			if ( j > 0 )
			{
				for ( i = 0; i < iHorNum; i ++ )
				{
					var bEnd = i == ( iHorNum - 1 );
					var row1 = bEnd ? 0 : i + 1;
					var row2 = ( bEnd ? iHorNum - 1 : i );
					var row3 = ( bEnd ? iHorNum - 1 : i );
					var row4 = bEnd ? 0 : i + 1;

					var aP1 = aVtc[j][row1];
					var aP2 = aVtc[j][row2];
					var aP3 = aVtc[j - 1][row3];
					var aP4 = aVtc[j - 1][row4];

					var fJ0 = j		 / ( iVerNum - 1 );
					var fJ1 = ( j - 1 )	 / ( iVerNum - 1 );
					var fI0 = ( i + 1 )	 / iHorNum;
					var fI1 = i		 / iHorNum;
						
					uvs.push( fI0, fJ1, 0.0 );
					uvs.push( fI0, fJ0, 0.0 );
					uvs.push( fI1, fJ0, 0.0 );
					uvs.push( fI1, fJ1, 0.0 );
					
					// 2 faces
					if ( j < ( aVtc.length - 1 ) )
					{
						vIndices.push( aP1 );
						vIndices.push( aP3 );
						vIndices.push( aP2 );
						tIndices.push( k + 1 );
						tIndices.push( k + 3 );
						tIndices.push( k + 2 );
					}
					if ( j > 1 )
					{
						vIndices.push( aP1 );
						vIndices.push( aP4 );
						vIndices.push( aP3 );
						tIndices.push( k + 1 );
						tIndices.push( k + 0 );
						tIndices.push( k + 3 );
					}

					k += 4;
				}
			}
		}
		
		this._vertices = vertices;
		this._indices = vIndices;
			
		var inputDatas = [
			new SmitearWebGL.Core.Geometry.InputDataSet( vIndices, vertices, 3 ),
			new SmitearWebGL.Core.Geometry.InputDataSet( tIndices, uvs, 3 )
		];
		
		var vOutputData = SmitearWebGL.Core.Geometry.Geometry.buildRawData( inputDatas );
		
		var vAdj = SmitearWebGL.Core.Geometry.Geometry.buildVertexAdjancency( inputDatas[0] );
		var fNormals = SmitearWebGL.Core.Geometry.Geometry.buildFaceNormal( inputDatas[0] );
		var nOutpuData = SmitearWebGL.Core.Geometry.Geometry.buildVertexNormal( inputDatas[0], vAdj, fNormals, new SmitearWebGL.Core.Geometry.InputDataSet( vOutputData.indices, null, 3 ) );
		
		var rawData = SmitearWebGL.Core.Geometry.Geometry.combineVertexDatas( [
			new SmitearWebGL.Core.Geometry.VertexDataSet( vOutputData.data, 6 ),
			new SmitearWebGL.Core.Geometry.VertexDataSet( nOutpuData.data, 3 ),
		] );
		
		this._boundingBox = SmitearWebGL.Core.Geometry.Geometry.computeBoundingBoxByRawVertices( vertices );

		var vertDescs = [
			new SmitearWebGL.Resources.VertexElementDescription( this.context.gl, 3, 36, 0, SmitearWebGL.Resources.Buffer.DataType.FLOAT, SmitearWebGL.Resources.Buffer.AttribLocation.POSITION ),
			new SmitearWebGL.Resources.VertexElementDescription( this.context.gl, 3, 36, 12, SmitearWebGL.Resources.Buffer.DataType.FLOAT, SmitearWebGL.Resources.Buffer.AttribLocation.TEXCOORD ),
			new SmitearWebGL.Resources.VertexElementDescription( this.context.gl, 3, 36, 24, SmitearWebGL.Resources.Buffer.DataType.FLOAT, SmitearWebGL.Resources.Buffer.AttribLocation.NORMAL )
		]
		
		var idxDescs = [
			new SmitearWebGL.Resources.IndexElementDescription( this.context.gl, vOutputData.indices.length, 0, SmitearWebGL.Resources.Buffer.DataType.UNSIGNED_SHORT, SmitearWebGL.Resources.IndexBuffer.DrawType.TRIANGLES )
		]
		
		this.createVertexBuffer( rawData, vertDescs );
		this.createIndexBuffer( vOutputData.indices, idxDescs );
	}
	,
	_createResource : function( params )
	{
		this._super();
		
		if ( ! params )
		{
			params = {};
			params.radius = 1.0;
			params.segmentsW = 8;
			params.segmentsH = 6;
		}
		
		this._build( params.radius, params.segmentsW, params.segmentsH );
	}
}
);